/*
 *  Segment.cpp
 *  openFrameworks
 *
 *  Created by allesblinkt on 5/4/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#include "Segment.h"

namespace abliefern {
	
	Segment::Segment(){
		x1 = 0;
		x2 = 0;
		y1 = 0;
		y2 = 0;
	}
	
	Segment::Segment(float theX1, float theY1, float theX2, float theY2){
		x1 = theX1;
		y1 = theY1;
		x2 = theX2;
		y2 = theY2;
	}
	
	float Segment::distanceToPoint(Point2f* thePoint){
		return distanceToPoint(this, thePoint->x, thePoint->y);
	}
	
	
	float Segment::distanceToPoint(float theX, float theY){
		return distanceToPoint(this, theX, theY);
	}
	
		
	float Segment::distanceToPoint(Segment* theSegment, Point2f* thePoint){
		return distanceToPoint(theSegment, thePoint->x, thePoint->y);
	}
	
	
	float Segment::squaredDistanceToPoint(Point2f* thePoint){
		return squaredDistanceToPoint(this, thePoint->x, thePoint->y);
	}
	
	
	float Segment::squaredDistanceToPoint(float theX, float theY){
		return squaredDistanceToPoint(this, theX, theY);
	}
	
	
	float Segment::squaredDistanceToPoint(Segment* theSegment, Point2f* thePoint){
		return squaredDistanceToPoint(theSegment, thePoint->x, thePoint->y);
	}
	
	
	float Segment::magnitude(){
		float myLength = x2 - x1;
		float myHeight = y2 - y1;

		return sqrt(myLength * myLength + myHeight * myHeight);
	}
	
	
	float Segment::squaredMagnitude(){
		float myLength = x2 - x1;
		float myHeight = y2 - y1;
		
		return myLength * myLength + myHeight * myHeight;
	}
	
	
	float Segment::distanceToPoint(Segment* theSegment, float theX, float theY){
		
		float myLineMagnitude = theSegment->magnitude();
		
		float myU = (( theX - theSegment->x1 ) * (theSegment->x2 - theSegment->x1) + (theY - theSegment->y1) * (theSegment->y2 - theSegment->y1))/
        ( myLineMagnitude * myLineMagnitude );
				
		float myX = theSegment->x1 + myU * ( theSegment->x2 - theSegment->x1 );
		float myY = theSegment->y1 + myU * ( theSegment->y2 - theSegment->y1 );

		return magnitude(myX, myY, theX, theY);
	}
	
	
	float Segment::squaredDistanceToPoint(Segment* theSegment, float theX, float theY){
		float myLineMagnitude = theSegment->magnitude();
		
		float myU = (( theX - theSegment->x1 ) * (theSegment->x2 - theSegment->x1) + (theY - theSegment->y1) * (theSegment->y2 - theSegment->y1))/
        ( myLineMagnitude * myLineMagnitude );
		
		float myX = theSegment->x1 + myU * ( theSegment->x2 - theSegment->x1 );
		float myY = theSegment->y1 + myU * ( theSegment->y2 - theSegment->y1 );
		
		return squaredMagnitude(myX, myY, theX, theY);
	}
	
	
	float Segment::angle(){
		return atan2(y2-y1, x2-x1);
	}
	
	
	Point2f* Segment::intersect(Segment* theSegment){
		return Segment::intersect(this, theSegment);
	}
	
	
	Point2f* Segment::intersect(Segment* theSegment1, Segment* theSegment2){
		float myNominator = (theSegment2->x2 - theSegment2->x1) * (theSegment1->y1 - theSegment2->y1) - (theSegment2->y2 - theSegment2->y1) * (theSegment1->x1 - theSegment2->x1);
		float myDenominator = (theSegment2->y2 - theSegment2->y1) * (theSegment1->x2 - theSegment1->x1) - (theSegment2->x2 - theSegment2->x1) * (theSegment1->y2 - theSegment1->y1);
		
		float ua = myNominator / myDenominator;
		
		
		if(myDenominator == 0) { // Segments are parallel
			return NULL;
		}
		
		float myX = (theSegment1->x1 + ua  * (theSegment1->x2 - theSegment1->x1));
		float myY = (theSegment1->y1 + ua *  (theSegment1->y2 - theSegment1->y1));
		
		Point2f* myPoint  = new Point2f;
		myPoint->x  = myX;
		myPoint->y = myY;
		
		return myPoint;
	}
	
	float Segment::magnitude(float theX1, float theY1, float theX2, float theY2){
		float myDiffX = theX2 - theX1;
		float myDiffY = theY2 - theY1;
		
		return sqrt(myDiffX * myDiffX + myDiffY * myDiffY);	
	}
	
	float Segment::squaredMagnitude(float theX1, float theY1, float theX2, float theY2){
		float myDiffX = theX2 - theX1;
		float myDiffY = theY2 - theY1;
		
		return myDiffX * myDiffX + myDiffY * myDiffY;	
	}
	
}

